home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 October: Mac OS SDK / Dev.CD Oct 97 SDK1.toast / Development Kits (Disc 1) / Apple Shared Library Manager / ASLM Examples / TestTools / Sources / TestTimeScheduler.cp < prev    next >
Encoding:
Text File  |  1996-11-19  |  21.8 KB  |  993 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        TestTimeScheduler.cp
  3.  
  4.     Contains:    Tester for the TTimeScheduler class
  5.  
  6.     Copyright:    © 1991-1994 by Apple Computer, Inc., all rights reserved.
  7.  
  8. */
  9.  
  10. #ifndef __TESTTIMESCHEDULER__
  11. #include "TestTimeScheduler.h"
  12. #endif
  13.  
  14. #ifndef __LIBRARYMANAGERUTILITIES__
  15. #include <LibraryManagerUtilities.h>
  16. #endif
  17.  
  18. const size_t    kNumOps    = 5;
  19.  
  20. #define kCloseness    1
  21.  
  22. size_t StringToNum(char* str);
  23. size_t RandomNumber(size_t lo, size_t hi);
  24.  
  25. /**********************************************************************
  26. ** TTimeOperation methods
  27. ***********************************************************************/
  28.  
  29. TTimeOperation::TTimeOperation(TTimeScheduler* theSched, int which)
  30. {
  31.     fSched    = theSched;
  32.     fTest    = 0;
  33.     fWatch    = NULL;
  34.     fWhich    = which;
  35.     fFired    = false;
  36. }
  37.  
  38. TTimeOperation::~TTimeOperation()
  39. {
  40.     if (fTest != 9)
  41.         DebugBreak("In TTimeOperation destructor when we shouldn't be!");
  42.     delete fWatch;
  43.     fTest = 10;
  44. }
  45.  
  46. void TTimeOperation::Process()
  47. {
  48.     switch (fTest)
  49.     {
  50.         case 0:
  51.             if (fFired)
  52.                 DebugBreak("Bummer - timer fired a second time");
  53.             fFired = true;
  54.             break;
  55.             
  56.         case 1:
  57.             if (fFired)
  58.                 DebugBreak("Bummer - timer fired a second time");
  59.             fFired = true;
  60.             if (!fSched->Remove(this))
  61.                 DebugBreak("Bummer - remove didn't work");
  62.             else
  63.             {
  64.                 if (!fSched->DeleteInProcessOperation(this))
  65.                     DebugBreak("Scheduler won't process DeleteInProcessOperation call");
  66.                 else
  67.                 {
  68.                     if (!WasRemovedInProcess())
  69.                         DebugBreak("WasRemovedInProcess returned false");
  70.                     ClearRemovedInProcess();
  71.                 }
  72.             }
  73.             break;
  74.             
  75.         case 2:
  76.             if (!fSched->Remove(this))
  77.                 DebugBreak("Bummer - remove didn't work");
  78.             else
  79.             {
  80.                 if (!fSched->RerunInProcessOperation(this))
  81.                     DebugBreak("Scheduler won't process RerunInProcessOperation call");
  82.                 else
  83.                 {
  84.                     if (!WasRemovedInProcess())
  85.                         DebugBreak("WasRemovedInProcess returned false");
  86.                     fTest = 3;
  87.                 }
  88.             }
  89.             break;
  90.  
  91.         case 3:
  92.             fFired = true;
  93.             if (!WasRemovedInProcess())
  94.                 DebugBreak("WasRemovedInProcess returned false");
  95.             ClearRemovedInProcess();
  96.             break;
  97.  
  98.         case 4:
  99.             fFired = true;
  100.             SetTime((kNumOps + 1)*500 - fWhich*500);
  101.             fTest = 5;
  102.             break;
  103.  
  104.         case 5:
  105.             if (!fFired)
  106.                 DebugBreak("Bummer - haven't already fired");
  107.             fTest = 20;
  108.             break;
  109.             
  110.         case 6:
  111.             fFired = true;
  112.             if (!fSched->Remove(this))
  113.                 DebugBreak("Bummer - remove didn't work");
  114.             SetTime((kNumOps + 1)*500 - fWhich*500);
  115.             fTest = 7;
  116.             fSched->Schedule(this);
  117.             break;
  118.  
  119.         case 7:
  120.             DebugBreak("Bummer - shouldn't get here");
  121.             fTest = 21;
  122.             break;
  123.             
  124.         case 8:
  125.             fFired = true;
  126.             SetDeleteWhenDone();
  127.             fTest = 9;
  128.             break;
  129.             
  130.         case 30:
  131.             unsigned long temp = fWatch->ElapsedMilliseconds();
  132.             fFired = true;
  133.             fDifference = (int)(temp - fWhen);
  134.             break;
  135.                             
  136.     }
  137. }
  138.  
  139. /**********************************************************************
  140. ** Class TTimeMatcher
  141. ***********************************************************************/
  142.  
  143. class TTimeMatcher : public TMatchObject
  144. {
  145.     public:
  146.                         TTimeMatcher(int toMatch);
  147.         virtual            ~_CDECL TTimeMatcher();
  148.         
  149.         virtual Boolean    _CDECL IsEqual(const void*) const;
  150.         
  151.         int    fMatch;
  152. };
  153.  
  154. TTimeMatcher::TTimeMatcher(int toMatch)
  155. {
  156.     fMatch = toMatch;
  157. }
  158.  
  159. TTimeMatcher::~TTimeMatcher()
  160. {}
  161.  
  162. Boolean TTimeMatcher::IsEqual(const void* obj) const
  163. {
  164.     return ((const TTimeOperation*)obj)->fWhich == fMatch;
  165. }
  166.  
  167. /**********************************************************************
  168. ** PUBLIC Constructor/Destructor 
  169. ***********************************************************************/
  170.  
  171. Constructor(TimeScheduler)
  172. Destructor(TimeScheduler)
  173.  
  174. /**********************************************************************
  175. ** PUBLIC InitTest
  176. ***********************************************************************/
  177.  
  178. void TTestTimeScheduler :: InitTest(BooleanParm, BooleanParm, int argc, char** argv)
  179. {    
  180.     size_t            idx;
  181.     TStandardPool*    pool = GetPool();
  182.  
  183.     if (pool == NULL)
  184.     {
  185.         Printf("### ERROR: There is no global pool\n");
  186.         return;
  187.     }
  188.         
  189.     if ((fTest = new (pool) TTimeScheduler) == NULL)
  190.         Printf("### ERROR: Couldn't create a new TTimeScheduler\n");
  191.         
  192.     fTest->SetAutoReschedule(true);
  193.     fNumOperations    = kNumOps;
  194.     fResolution        = 50;
  195.     fIterations        = 100;
  196.     fStress            = false;
  197.     fMaxSchedule    = 2500;
  198.     fMinSchedule    = 1;
  199.     idx = 0;
  200.     while (argc)
  201.     {
  202.         char*    str;
  203.         
  204.         str = argv[idx];
  205.         if (*str != '-')
  206.             break;
  207.         argc -= 1;
  208.         idx += 1;
  209.         switch (str[1])
  210.         {
  211.             case 'n':
  212.             case 'N':
  213.                 fNumOperations = StringToNum(argv[idx++]);
  214.                 argc -= 1;
  215.                 break;
  216.             
  217.             case 'm':
  218.             case 'M':
  219.                 if (argc >= 2)
  220.                 {    
  221.                     fMinSchedule = StringToNum(argv[idx++]);
  222.                     fMaxSchedule = StringToNum(argv[idx++]);
  223.                     argc -= 2;
  224.                     if (fMinSchedule == 0 || fMaxSchedule == 0 ||
  225.                         fMinSchedule > fMaxSchedule)
  226.                     {
  227.                         fMaxSchedule    = 2500;
  228.                         fMinSchedule    = 1;
  229.                         Printf("WARNING: -m option expects min and max time following\n", str);
  230.                     }
  231.                 }
  232.                 else
  233.                 {
  234.                     Printf("WARNING: Option at and after '-m' not understood!\n", str);
  235.                 }
  236.                 break;
  237.                 
  238.             case 'r':
  239.             case 'R':
  240.                 fResolution = StringToNum(argv[idx++]);
  241.                 argc -= 1;
  242.                 break;
  243.                 
  244.             case 'i':
  245.             case 'I':
  246.                 fIterations = StringToNum(argv[idx++]);
  247.                 argc -= 1;
  248.                 break;
  249.                 
  250.             case 's':
  251.             case 'S':
  252.                 fStress = true;
  253.                 break;
  254.                 
  255.             default: 
  256.                 argc = 0;
  257.                 Printf("WARNING: Option at and after '%s' not understood!\n", str);
  258.                 break;
  259.         }
  260.  
  261.     }
  262.     if (fStress)
  263.     {
  264.         Printf("\nINFO: Running %u iterations of %u operations, resolution = %u\n",
  265.                fIterations, fNumOperations, fResolution);
  266.         Printf("INFO: Random Schedule from %u to %u milliseconds\n", 
  267.                 fMinSchedule, fMaxSchedule);
  268.     }
  269. }
  270.  
  271. /*******************************************************************************
  272. ** PUBLIC RunStressTest
  273. ********************************************************************************/
  274.  
  275. void TTestTimeScheduler::RunStressTest(Boolean)
  276. {
  277.     size_t                idx, jdx;
  278.     TTimeOperation**    ops;
  279.     unsigned long        sum[3];
  280.     unsigned long        sum2[3];
  281.     unsigned long        total[3];
  282.         
  283.     sum[0] = 0;
  284.     sum[1] = 0;
  285.     sum[2] = 0;
  286.     sum2[0] = 0;
  287.     sum2[1] = 0;
  288.     sum2[2] = 0;
  289.     total[0] = 0;
  290.     total[1] = 0;
  291.     total[2] = 0;
  292.     ops = new TTimeOperation*[fNumOperations];
  293.     if (ops == NULL)
  294.     {
  295.         Printf("ERROR: Out of Memory\n");
  296.         return;
  297.     }
  298.     size_t count = 0;
  299.     for (idx = 0; idx < fNumOperations; ++idx)
  300.     {
  301.         ops[idx] = new TTimeOperation(fTest, idx);
  302.         if (ops[idx])
  303.         {
  304.             ops[idx]->fTest = 30;
  305.             ops[idx]->fWatch = new TStopwatch;
  306.             ops[idx]->fWhen = RandomNumber(fMinSchedule, fMaxSchedule);
  307.             ops[idx]->SetTime(ops[idx]->fWhen);
  308.             if (ops[idx]->fWatch == NULL)
  309.             {
  310.                 delete ops[idx];
  311.                 ops[idx] = NULL;
  312.             }
  313.             else
  314.                 count += 1;
  315.         }
  316.     }
  317.     if (count == 0)
  318.     {
  319.         Printf("ERROR: Out of Memory\n");
  320.         return;
  321.     }
  322.     if (count != fNumOperations)
  323.     {
  324.         Printf("WARNING: Only enough memory to create %u operations\n", count);
  325.     }
  326.     for (jdx = 0; jdx < fNumOperations; ++jdx)
  327.     {
  328.         if (ops[jdx])
  329.             fTest->Schedule(ops[jdx]);
  330.     }
  331.     Printf("       0: ");
  332.     for (idx = 0; idx < fIterations; ++idx)
  333.     {
  334.         Printf(".");
  335.         if ((idx + 1) % 50 == 0)
  336.             Printf("\n%8u: ", idx + 1);
  337.         size_t cnt = 0;
  338.         while (cnt < count)
  339.         {
  340.             for (jdx = 0; jdx < fNumOperations; ++jdx)
  341.             {
  342.                 if (ops[jdx] && ops[jdx]->fFired)
  343.                 {
  344.                     int    diff = ops[jdx]->fDifference;
  345.                     sum[0] += diff;
  346.                     sum2[0] += diff*diff;
  347.                     total[0] += 1;
  348.                     if (diff < 0)
  349.                     {
  350.                         sum[1] -= diff;
  351.                         sum2[1] += diff*diff;
  352.                         total[1] += 1;
  353.                     }
  354.                     else if (diff > 0)
  355.                     {
  356.                         sum[2] += diff;
  357.                         sum2[2] += diff*diff;
  358.                         total[2] += 1;
  359.                     }
  360.                     
  361.                     cnt += 1;
  362.                     ops[jdx]->fFired = false;
  363.                     ops[jdx]->fWhen = RandomNumber(fMinSchedule, fMaxSchedule);
  364.                     ops[jdx]->SetTime(ops[jdx]->fWhen);
  365.                     ops[jdx]->fWatch->Reset();
  366.                     fTest->Schedule(ops[jdx]);
  367.                 }
  368.             }
  369.         }
  370.     }
  371.     Printf("\nEnd of Test\n");
  372.     Printf("Total fired   = %u\n", total[0]);
  373.     Printf("Average error = %u milliseconds\n", sum[0]/total[0]);
  374.     Printf("Variance      = %u\n\n",
  375.            (total[0]*sum2[0] - sum[0]*sum[0])/(total[0]*(total[0] - 1)));
  376.     if (total[1] > 1)
  377.     {
  378.         Printf("Total early fires = %u\n", total[1]);
  379.         Printf("Average error     = %u milliseconds\n", sum[1]/total[1]);
  380.         Printf("Variance          = %u\n\n",
  381.                (total[1]*sum2[1] - sum[1]*sum[1])/(total[1]*(total[1] - 1)));
  382.     }
  383.     if (total[2] > 1)
  384.     {
  385.         Printf("Total late fires = %u\n", total[2]);
  386.         Printf("Average error     = %u milliseconds\n", sum[2]/total[2]);
  387.         Printf("Variance          = %u\n\n",
  388.                (total[2]*sum2[2] - sum[2]*sum[2])/(total[2]*(total[2] - 1)));
  389.     }
  390.     jdx = 0;
  391.     while (jdx < fNumOperations)
  392.     {
  393.         if (ops[jdx] == NULL || ops[jdx]->fFired)
  394.         {
  395.             if (ops[jdx])
  396.             {
  397.                 ops[jdx]->fTest = 9;
  398.                 delete ops[jdx];
  399.             }
  400.             jdx += 1;
  401.         }
  402.     }
  403.     delete ops;
  404. }
  405.  
  406. /**********************************************************************
  407. ** PUBLIC RunTestIteration
  408. ***********************************************************************/
  409.  
  410. void TTestTimeScheduler :: RunTestIteration(BooleanParm verbose, BooleanParm)
  411. {
  412.     if (fStress)
  413.     {
  414.         RunStressTest(verbose);
  415.         return;
  416.     }
  417.     
  418.     unsigned short    idx, jdx;
  419.     Boolean            flags[kNumOps];
  420.     TTimeOperation*    ops[kNumOps];
  421.     TStopwatch*        start;
  422.     unsigned long    timers[kNumOps];
  423.     unsigned long    stamps[kNumOps];
  424.     unsigned short    num = kNumOps;
  425.     
  426.     if (verbose)
  427.         Printf("INFO: Creating %u TTimeOperation objects\n", num);
  428.  
  429.     for (idx = 0; idx < num; ++idx)
  430.     {
  431.         ops[idx] = new TTimeOperation(fTest, idx);
  432.         ops[idx]->fTest = 0;
  433.     }
  434.     start = new TStopwatch;
  435.         
  436. /*    -----------------------------------------------------------------
  437.     First, try 1 and 10 milliseconds resolution with a straightforward
  438.     scheduling
  439.     ----------------------------------------------------------------- */
  440.  
  441.     for (idx = 0; idx < 2; ++idx)
  442.     {
  443.         if (verbose)
  444.         {
  445.             Printf("INFO: Testing scheduling ");
  446.             if (idx == 0)
  447.                 Printf("forward   ");
  448.             else
  449.                 Printf("backwards ");
  450.             Printf("  ");
  451.         }
  452.         for (jdx = 0; jdx < num; ++jdx)
  453.         {
  454.             timers[jdx] = jdx*1000 + 1000;
  455.             ops[jdx]->fFired = 0;
  456.             ops[jdx]->SetTime(timers[jdx]);
  457.             flags[jdx] = 0;
  458.         }
  459.         
  460.         start->Reset();
  461.         if (idx != 0)
  462.         {
  463.             for (jdx = 0; jdx < num; ++jdx)
  464.                 fTest->Schedule(ops[num - 1 - jdx]);
  465.         }
  466.         else
  467.             for (jdx = 0; jdx < num; ++jdx)
  468.                 fTest->Schedule(ops[jdx]);
  469.  
  470.         if (fTest->IsEmpty())
  471.             Printf("\n ERROR: TTimeScheduler thinks it is empty when it is not!\n");
  472.  
  473.         Boolean ready = false;
  474.         while (!ready)
  475.         {
  476.             ready = true;
  477.             for (jdx = 0; jdx < num; ++jdx)
  478.                 if (!flags[jdx])
  479.                 {
  480.                     ready = false;
  481.                     break;
  482.                 }
  483.                 
  484.             for (jdx = 0; jdx < num; ++jdx)
  485.                 if (!flags[jdx])
  486.                     if (ops[jdx]->fFired)
  487.                     {
  488.                         flags[jdx] = true;
  489.                         stamps[jdx] = start->ElapsedMilliseconds();
  490.                         Printf(".");
  491.                     }
  492.         }
  493.         Printf("\n");
  494.         for (jdx = 0; jdx < num; ++jdx)
  495.         {
  496.             if (stamps[jdx] < timers[jdx] - kCloseness || stamps[jdx] > timers[jdx] + kCloseness)
  497.                 Printf(" WARNING: Timer%u (%u) fired at T=%u milliseconds\n", jdx + 1, timers[jdx],
  498.                         stamps[jdx]);
  499.         }
  500.     }
  501.     if (!fTest->IsEmpty())
  502.         Printf(" ERROR: TTimeScheduler does not think it is empty!\n");
  503.     for (idx = 0; idx < num - 1; ++idx)
  504.     {
  505.         if (verbose)
  506.             Printf("INFO: Testing Duplicate on #%u  ", idx + 1);
  507.         for (jdx = 0; jdx < num - 1; ++jdx)
  508.                 timers[jdx] = jdx*500 + 500;
  509.         
  510.         timers[num - 1] = timers[idx];
  511.         
  512.         for (jdx = 0; jdx < num; ++jdx)
  513.         {
  514.             ops[jdx]->fFired = 0;
  515.             ops[jdx]->SetTime(timers[jdx]);
  516.             flags[jdx] = 0;
  517.         }
  518.         
  519.         start->Reset();
  520.         for (jdx = 0; jdx < num; ++jdx)
  521.             fTest->Schedule(ops[jdx]);
  522.  
  523.         if (fTest->IsEmpty())
  524.             Printf("\n ERROR: TTimeScheduler thinks it is empty when it is not!\n");
  525.  
  526.         Boolean ready = false;
  527.         while (!ready && start->ElapsedMilliseconds() < timers[num - 2] + 500)
  528.         {
  529.             ready = true;
  530.             for (jdx = 0; jdx < num; ++jdx)
  531.                 if (!flags[jdx])
  532.                 {
  533.                     ready = false;
  534.                     break;
  535.                 }
  536.                 
  537.             short dots = 0;
  538.             for (jdx = 0; jdx < num; ++jdx)
  539.                 if (!flags[jdx])
  540.                     if (ops[jdx]->fFired)
  541.                     {
  542.                         flags[jdx] = true;
  543.                         stamps[jdx] = start->ElapsedMilliseconds();
  544.                         ++dots;
  545.                     }
  546.             while (dots--)
  547.                 Printf(".");
  548.         }
  549.         Printf("\n");
  550.         for (jdx = 0; jdx < num; ++jdx)
  551.         {
  552.             if (stamps[jdx] < timers[jdx] - kCloseness || stamps[jdx] > timers[jdx] + kCloseness)
  553.                 Printf(" WARNING: Timer%u (%u) fired at T=%u milliseconds\n", jdx + 1, timers[jdx],
  554.                         stamps[jdx]);
  555.         }
  556.     }
  557.     if (!fTest->IsEmpty())
  558.         Printf(" ERROR: TTimeScheduler does not think it is empty!\n");
  559.         
  560.     for (idx = 0; idx < num; ++idx)
  561.     {
  562.         if (verbose)
  563.             Printf("INFO: Testing Removal by pointer of #%u  ", idx + 1);
  564.             
  565.         for (jdx = 0; jdx < num; ++jdx)
  566.             timers[jdx] = jdx*500 + 500;
  567.         
  568.         for (jdx = 0; jdx < num; ++jdx)
  569.         {
  570.             ops[jdx]->fFired = 0;
  571.             ops[jdx]->SetTime(timers[jdx]);
  572.             flags[jdx] = 0;
  573.         }
  574.         
  575.         start->Reset();
  576.         for (jdx = 0; jdx < num; ++jdx)
  577.             fTest->Schedule(ops[jdx]);
  578.  
  579.         if (fTest->IsEmpty())
  580.             Printf("\n ERROR: TTimeScheduler thinks it is empty when it is not!\n");
  581.  
  582.         if (!fTest->Remove(ops[idx]))
  583.             Printf("\n ERROR: Removal of Timer #%u failed\n", idx + 1);
  584.             
  585.         Boolean ready = false;
  586.         while (!ready && (idx != num - 1 || start->ElapsedMilliseconds() < timers[num - 1] + 500))
  587.         {
  588.             ready = true;
  589.             for (jdx = 0; jdx < num; ++jdx)
  590.                 if (jdx != idx)
  591.                     if (!flags[jdx])
  592.                     {
  593.                         ready = false;
  594.                         break;
  595.                     }
  596.                 
  597.             for (jdx = 0; jdx < num; ++jdx)
  598.                 if (!flags[jdx])
  599.                     if (ops[jdx]->fFired)
  600.                     {
  601.                         flags[jdx] = true;
  602.                         stamps[jdx] = start->ElapsedMilliseconds();
  603.                         Printf(".");
  604.                         if (jdx == idx)
  605.                             Printf("\n ERROR: Bummer - Timer #%u Fired\n", jdx + 1);
  606.                     }
  607.         }
  608.         Printf("\n");
  609.         for (jdx = 0; jdx < num; ++jdx)
  610.         {
  611.             if (ops[jdx]->fFired == 0)
  612.                 continue;
  613.             if (stamps[jdx] < timers[jdx] - kCloseness || stamps[jdx] > timers[jdx] + kCloseness)
  614.                 Printf(" WARNING: Timer%u (%u) fired at T=%u milliseconds\n", jdx + 1, timers[jdx],
  615.                         stamps[jdx]);
  616.         }
  617.         if (!fTest->IsEmpty())
  618.             Printf(" ERROR: TTimeScheduler does not think it is empty!\n");
  619.     }
  620.     
  621.     for (idx = 0; idx < num; ++idx)
  622.     {
  623.         TTimeMatcher    match(idx);
  624.         
  625.         if (verbose)
  626.             Printf("INFO: Testing Removal by matchObject of #%u  ", idx + 1);
  627.             
  628.         for (jdx = 0; jdx < num; ++jdx)
  629.             timers[jdx] = jdx*500 + 500;
  630.         
  631.         for (jdx = 0; jdx < num; ++jdx)
  632.         {
  633.             ops[jdx]->fFired = 0;
  634.             ops[jdx]->SetTime(timers[jdx]);
  635.             flags[jdx] = 0;
  636.         }
  637.         
  638.         start->Reset();
  639.         for (jdx = 0; jdx < num; ++jdx)
  640.             fTest->Schedule(ops[jdx]);
  641.  
  642.         if (fTest->IsEmpty())
  643.             Printf("\n ERROR: TTimeScheduler thinks it is empty when it is not!\n");
  644.  
  645.         TOperation* op = fTest->Remove(match);
  646.         if (!op)
  647.             Printf("\n ERROR: Removal of Timer #%u failed\n", idx + 1);
  648.         if (op != ops[idx])
  649.             Printf("\n ERROR: Removal of Timer #%u did not return the correct operation\n", idx + 1);
  650.             
  651.         Boolean ready = false;
  652.         while (!ready && (idx != num - 1 || start->ElapsedMilliseconds() < timers[num - 1] + 500))
  653.         {
  654.             ready = true;
  655.             for (jdx = 0; jdx < num; ++jdx)
  656.                 if (jdx != idx)
  657.                     if (!flags[jdx])
  658.                     {
  659.                         ready = false;
  660.                         break;
  661.                     }
  662.                 
  663.             for (jdx = 0; jdx < num; ++jdx)
  664.                 if (!flags[jdx])
  665.                     if (ops[jdx]->fFired)
  666.                     {
  667.                         flags[jdx] = true;
  668.                         stamps[jdx] = start->ElapsedMilliseconds();
  669.                         Printf(".");
  670.                         if (jdx == idx)
  671.                             Printf("\n ERROR: Bummer - Timer #%u Fired\n", jdx + 1);
  672.                     }
  673.         }
  674.         Printf("\n");
  675.         for (jdx = 0; jdx < num; ++jdx)
  676.         {
  677.             if (ops[jdx]->fFired == 0)
  678.                 continue;
  679.             if (stamps[jdx] < timers[jdx] - kCloseness || stamps[jdx] > timers[jdx] + kCloseness)
  680.                 Printf(" WARNING: Timer%u (%u) fired at T=%u milliseconds\n", jdx + 1, timers[jdx],
  681.                         stamps[jdx]);
  682.         }
  683.         if (!fTest->IsEmpty())
  684.             Printf(" ERROR: TTimeScheduler does not think it is empty!\n");
  685.     }
  686.     
  687.     
  688.     for (idx = 0; idx < num; ++idx)
  689.     {
  690.         if (verbose)
  691.             Printf("INFO: Testing Removal/Acknowledge while in Process of #%u  ", idx + 1);
  692.             
  693.         for (jdx = 0; jdx < num; ++jdx)
  694.             timers[jdx] = jdx*500 + 500;
  695.         
  696.         for (jdx = 0; jdx < num; ++jdx)
  697.         {
  698.             ops[jdx]->fFired = 0;
  699.             ops[jdx]->fTest = 0;
  700.             ops[jdx]->SetTime(timers[jdx]);
  701.             flags[jdx] = 0;
  702.         }
  703.         ops[idx]->fTest = 1;
  704.         
  705.         start->Reset();
  706.         for (jdx = 0; jdx < num; ++jdx)
  707.             fTest->Schedule(ops[jdx]);
  708.  
  709.         if (fTest->IsEmpty())
  710.             Printf("\n ERROR: TTimeScheduler thinks it is empty when it is not!\n");
  711.  
  712.         Boolean ready = false;
  713.         while (!ready)
  714.         {
  715.             ready = true;
  716.             for (jdx = 0; jdx < num; ++jdx)
  717.                 if (!flags[jdx])
  718.                 {
  719.                     ready = false;
  720.                     break;
  721.                 }
  722.                 
  723.             for (jdx = 0; jdx < num; ++jdx)
  724.                 if (!flags[jdx])
  725.                     if (ops[jdx]->fFired)
  726.                     {
  727.                         flags[jdx] = true;
  728.                         stamps[jdx] = start->ElapsedMilliseconds();
  729.                         Printf(".");
  730.                     }
  731.         }
  732.         Printf("\n");
  733.         if (!fTest->IsEmpty())
  734.             Printf(" ERROR: TTimeScheduler does not think it is empty!\n");
  735.     }
  736.     
  737.     for (idx = 0; idx < num; ++idx)
  738.     {
  739.         if (verbose)
  740.             Printf("INFO: Testing Removal/Rerun while in Process of #%u  ", idx + 1);
  741.             
  742.         for (jdx = 0; jdx < num; ++jdx)
  743.             timers[jdx] = jdx*500 + 500;
  744.         
  745.         for (jdx = 0; jdx < num; ++jdx)
  746.         {
  747.             ops[jdx]->fFired = 0;
  748.             ops[jdx]->fTest = 0;
  749.             ops[jdx]->SetTime(timers[jdx]);
  750.             flags[jdx] = 0;
  751.         }
  752.         ops[idx]->fTest = 2;
  753.         
  754.         start->Reset();
  755.         for (jdx = 0; jdx < num; ++jdx)
  756.             fTest->Schedule(ops[jdx]);
  757.  
  758.         if (fTest->IsEmpty())
  759.             Printf("\n ERROR: TTimeScheduler thinks it is empty when it is not!\n");
  760.  
  761.         Boolean ready = false;
  762.         while (!ready)
  763.         {
  764.             ready = true;
  765.             for (jdx = 0; jdx < num; ++jdx)
  766.                 if (!flags[jdx])
  767.                 {
  768.                     ready = false;
  769.                     break;
  770.                 }
  771.                 
  772.             for (jdx = 0; jdx < num; ++jdx)
  773.                 if (!flags[jdx])
  774.                     if (ops[jdx]->fFired)
  775.                     {
  776.                         flags[jdx] = true;
  777.                         stamps[jdx] = start->ElapsedMilliseconds();
  778.                         Printf(".");
  779.                     }
  780.         }
  781.         Printf("\n");
  782.         if (!fTest->IsEmpty())
  783.             Printf(" ERROR: TTimeScheduler does not think it is empty!\n");
  784.     }
  785.     
  786.     
  787.     if (verbose)
  788.         Printf("INFO: Testing single Reschedule\n");
  789.     timers[0] = 1000;
  790.     ops[0]->fFired = 0;
  791.     ops[0]->fTest = 0;
  792.     ops[0]->SetTime(timers[0]);
  793.     flags[0] = 0;
  794.     start->Reset();
  795.     fTest->Schedule(ops[0]);
  796.     if (fTest->IsEmpty())
  797.         Printf("ERROR: TTimeScheduler thinks it is empty when it is not!\n");
  798.     if (!fTest->Remove(ops[0]))
  799.         Printf("ERROR: could not remove the TOperation!\n");
  800.     else
  801.     {
  802.         ops[0]->SetTime(3000);
  803.         timers[0] = 3000;
  804.         fTest->Schedule(ops[0]);
  805.     }
  806.     while (ops[0]->fFired == 0)
  807.         ;
  808.     stamps[0] = start->ElapsedMilliseconds();
  809.     if (stamps[0] < 3000 - kCloseness || stamps[0] > 3000 + kCloseness)
  810.     {
  811.         Printf("WARNING: Timer fired at %u\n", stamps[0]);
  812.     }
  813.         
  814.     for (idx = 0; idx < num; ++idx)
  815.     {
  816.         if (verbose)
  817.             Printf("INFO: Testing Reschedule while in Process of #%u  ", idx + 1);
  818.             
  819.         for (jdx = 0; jdx < num; ++jdx)
  820.             timers[jdx] = jdx*500 + 500;
  821.         
  822.         for (jdx = 0; jdx < num; ++jdx)
  823.         {
  824.             ops[jdx]->fFired = 0;
  825.             ops[jdx]->fTest = 0;
  826.             ops[jdx]->SetTime(timers[jdx]);
  827.             flags[jdx] = 0;
  828.         }
  829.         ops[idx]->fTest = 4;
  830.         
  831.         start->Reset();
  832.         for (jdx = 0; jdx < num; ++jdx)
  833.             fTest->Schedule(ops[jdx]);
  834.  
  835.         if (fTest->IsEmpty())
  836.             Printf("\n ERROR: TTimeScheduler thinks it is empty when it is not!\n");
  837.  
  838.         Boolean ready = false;
  839.         while (!ready)
  840.         {
  841.             ready = true;
  842.             for (jdx = 0; jdx < num; ++jdx)
  843.                 if (!flags[jdx])
  844.                 {
  845.                     ready = false;
  846.                     break;
  847.                 }
  848.                 
  849.             for (jdx = 0; jdx < num; ++jdx)
  850.                 if (!flags[jdx])
  851.                     if (ops[jdx]->fFired)
  852.                     {
  853.                         flags[jdx] = true;
  854.                         stamps[jdx] = start->ElapsedMilliseconds();
  855.                         Printf(".");
  856.                     }
  857.         }
  858.         while (ops[idx]->fTest != 20 && start->ElapsedMilliseconds() < num*1000)
  859.             ;
  860.         stamps[idx] = start->ElapsedMilliseconds();
  861.         Printf("\n");
  862.         if (ops[idx]->fTest != 20)
  863.             Printf(" ERROR: Timer#%u did not fire a second time\n", idx + 1);
  864.         else
  865.             if (stamps[idx] < 3500 - kCloseness || stamps[idx] > 3500 + kCloseness)
  866.             {
  867.                 Printf(" WARNING: Timer#%u (%u) fired at %u\n",
  868.                        idx + 1, 3500, stamps[idx]);
  869.             }
  870.         if (!fTest->IsEmpty())
  871.             Printf(" ERROR: TTimeScheduler does not think it is empty!\n");
  872.     }
  873.     
  874.     for (idx = 0; idx < num; ++idx)
  875.     {
  876.         if (verbose)
  877.             Printf("INFO: Testing Remove/Reschedule while in Process of #%u  ", idx + 1);
  878.             
  879.         for (jdx = 0; jdx < num; ++jdx)
  880.             timers[jdx] = jdx*500 + 500;
  881.         
  882.         for (jdx = 0; jdx < num; ++jdx)
  883.         {
  884.             ops[jdx]->fFired = 0;
  885.             ops[jdx]->fTest = 0;
  886.             ops[jdx]->SetTime(timers[jdx]);
  887.             flags[jdx] = 0;
  888.         }
  889.         ops[idx]->fTest = 6;
  890.         
  891.         start->Reset();
  892.         for (jdx = 0; jdx < num; ++jdx)
  893.             fTest->Schedule(ops[jdx]);
  894.  
  895.         if (fTest->IsEmpty())
  896.             Printf("\n ERROR: TTimeScheduler thinks it is empty when it is not!\n");
  897.  
  898.         Boolean ready = false;
  899.         while (!ready)
  900.         {
  901.             ready = true;
  902.             for (jdx = 0; jdx < num; ++jdx)
  903.                 if (!flags[jdx])
  904.                 {
  905.                     ready = false;
  906.                     break;
  907.                 }
  908.                 
  909.             for (jdx = 0; jdx < num; ++jdx)
  910.                 if (!flags[jdx])
  911.                     if (ops[jdx]->fFired)
  912.                     {
  913.                         flags[jdx] = true;
  914.                         stamps[jdx] = start->ElapsedMilliseconds();
  915.                         Printf(".");
  916.                     }
  917.         }
  918.         Printf("\n");
  919.         if (!fTest->IsEmpty())
  920.         {
  921.             Printf(" ERROR: TTimeScheduler does not think it is empty!\n");
  922.             while (ops[idx]->fTest != 21 && start->ElapsedMilliseconds() < num*1000)
  923.                 ;
  924.             if (ops[idx]->fTest == 21)
  925.                 Printf(" ERROR: Timer#%u fired a second time\n", idx + 1);
  926.         }
  927.     }
  928.  
  929.     if (verbose)
  930.         Printf("INFO: Testing Removal/Delete  ", idx + 1);
  931.         
  932.     for (jdx = 0; jdx < num; ++jdx)
  933.         timers[jdx] = jdx*500 + 500;
  934.     
  935.     for (jdx = 0; jdx < num; ++jdx)
  936.     {
  937.         ops[jdx]->fFired = 0;
  938.         ops[jdx]->fTest = 8;
  939.         ops[jdx]->SetTime(timers[jdx]);
  940.         flags[jdx] = 0;
  941.     }
  942.     
  943.     start->Reset();
  944.     for (jdx = 0; jdx < num; ++jdx)
  945.         fTest->Schedule(ops[jdx]);
  946.  
  947.     if (fTest->IsEmpty())
  948.         Printf("\n ERROR: TTimeScheduler thinks it is empty when it is not!\n");
  949.  
  950.     Boolean ready = false;
  951.     while (!ready)
  952.     {
  953.         ready = true;
  954.         for (jdx = 0; jdx < num; ++jdx)
  955.             if (!flags[jdx])
  956.             {
  957.                 ready = false;
  958.                 break;
  959.             }
  960.             
  961.         for (jdx = 0; jdx < num; ++jdx)
  962.             if (!flags[jdx])
  963.                 if (ops[jdx]->fFired)
  964.                 {
  965.                     flags[jdx] = true;
  966.                     stamps[jdx] = start->ElapsedMilliseconds();
  967.                     Printf(".");
  968.                 }
  969.     }
  970.     Printf("\n");
  971.     for (jdx = 0; jdx < num; ++jdx)
  972.     {
  973.         if (ops[jdx]->fTest != 10)
  974.             Printf("ERROR: Timer%u (%u) did not delete itself\n", jdx + 1, timers[jdx]);
  975.         if (ops[jdx]->fFired == 0)
  976.             continue;
  977.     }
  978.     if (!fTest->IsEmpty())
  979.         Printf(" ERROR: TTimeScheduler does not think it is empty!\n");
  980.  
  981.     delete start;
  982. }
  983.  
  984. /**********************************************************************
  985. ** PUBLIC EndTest
  986. ***********************************************************************/
  987.  
  988. void TTestTimeScheduler :: EndTest(BooleanParm, BooleanParm)
  989. {
  990.     delete fTest;
  991.     fTest = NULL;
  992. }
  993.